/******************************************************************************************/
/* Demo2 de UCOS-II                                                                       */
/*    Programme qui lance 4 taches, chaque tache faisant clignoter un LED                 */
/*    Implique l'utilisation de semaphore, mailbox et messageQueue.                       */
/*    Implique l'utilisation de USART1, mais sans interruption.                       */
/* - Ne pas inclure le Framework INTC, utiliser les appels fourni par BSP.c..             */
/* - Les principaux FRAMEWORK-DRIVER GPIO, USART, ADC, FLASH PM sont deja dispo (include) */
/******************************************************************************************/
#include  "includes.h"
#include  "gpio.h"
#include  "led.h"
#include "usart.h"
#include "print_funcs.h"

/**** Reservation du STACK de chaque tache ************************************************/
#define OS_TASK_STK_SIZE 256
OS_STK  Task1_Stk[OS_TASK_STK_SIZE];
OS_STK  Task2_Stk[OS_TASK_STK_SIZE];
OS_STK  Task3_Stk[OS_TASK_STK_SIZE];
OS_STK  Task4_Stk[OS_TASK_STK_SIZE];

static  void  Task1(void *p_arg);
static  void  Task2(void *p_arg);
static  void  Task3(void *p_arg);
static  void  Task4(void *p_arg);

OS_EVENT	*Sema1;		// Semaphore
OS_EVENT	*Sema2;		// Semaphore
OS_EVENT	*Sema3;		// Semaphore
OS_EVENT	*Mbox1;		// Semaphore
OS_EVENT	*MsgQ1;		// Mailbox

void  *MyMsgQ[3];		// Ma MessageQueue (FIFO)
void Init_IO_Usager(void);          // Fonction definie localement

/**** Fonction principale main()***********************************************************/
int  main (void)
{
    CPU_IntDis();       /* Descative toute les interrupts pendant l'initialisation  */
    OSInit();           /* Initialise "uC/OS-II, The Real-Time Kernel"              */

    /* Creation de toute les taches...a des priorites differentes (5<prio<28) */
    OSTaskCreate(Task1, NULL, (OS_STK *)&Task1_Stk[OS_TASK_STK_SIZE-1], 6);
    OSTaskCreate(Task2, NULL, (OS_STK *)&Task2_Stk[OS_TASK_STK_SIZE-1], 7);
    OSTaskCreate(Task3, NULL, (OS_STK *)&Task3_Stk[OS_TASK_STK_SIZE-1], 8);
    OSTaskCreate(Task4, NULL, (OS_STK *)&Task4_Stk[OS_TASK_STK_SIZE-1], 9);

    Sema1   = OSSemCreate(0);		// Semaphore, initialisation
    Sema3   = OSSemCreate(0);		// Semaphore, initialisation
    Mbox1   = OSMboxCreate(NULL);   // MailBox,   initialisation
    MsgQ1   = OSQCreate(MyMsgQ, 3); // MailBox,   initialisation

    OSStart();          /* Demarre le multitasking (Donne le controle au noyau uC/OS-II)  */
    // Le code ici ne sera jamais execute
    return (0);         /* Pour eviter le warnings en GCC, prototype (int main (void))    */
}

/******************************************************************************************/
/* Definition des taches sous UCOS-II                                                     */
/*  - Toutes les taches ont une priorite differente                                       */
/*  - Le scheduler de UCOS-II execute TOUJOURS la tache la plus prioritaire qui est READY.*/
/******************************************************************************************/

/******************************************************************************************/
static  void  Task1 (void *p_arg)
{
//  OS_CPU_SR  cpu_sr = 0;  /* stockage local requis par macro OS_ENTER/EXIT_CRITICAL */
    (void)p_arg;          // Pour eviter le warnings en GCC
    U8 err; U8 MsgQDataRX;

    BSP_Init();           // Set le timer et demarre les ISR_TICKS.
						  // Doit absolument etre appele par la premiere tache a operer.
						  // Attention, desormais on roule a 48MHz et USART a 48/2MHz

	CPU_IntDis();		  // Desactive les IRQ pendant l'initialisation
    Init_IO_Usager();     // Initialisation des differents I/O par l'usager, requis ici car much init (irq table,)dne in BSP_init
	CPU_IntEn();		  // Reactive les IRQ

	LED_Toggle(LED4);
 /*---Fin de l'initialisation----------*/

    while (1) {           // Tache, une boucle infinie.
    	MsgQDataRX=*((U8 *)OSQPend(MsgQ1, 0, &err));  // Attend le MessageQueue
    	print_dbg_char(MsgQDataRX);
    	LED_Toggle(LED0);
    }
}
/******************************************************************************************/
static  void  Task2 (void *p_arg)
{
   (void)p_arg; U8 err; U8 MboxDataRX; U8 MsgQDataPost;
   MsgQDataPost='a';

    while (1) {
    	MsgQDataPost++;
    	if(MsgQDataPost>'z') MsgQDataPost='a';
    	MboxDataRX=*((U8 *)OSMboxPend(Mbox1, 0, &err));  // Attend le mailbox
    	LED_Toggle(LED1);
		OSQPost(MsgQ1, &MsgQDataPost);
    }
}
/******************************************************************************************/
static  void  Task3 (void *p_arg)
{
    (void)p_arg; U8 err; U8 MboxDataPost;
    MboxDataPost='3';

    while (1) {
    	OSSemPend(Sema1, 0, &err);  // Attend le semaphore
    	LED_Toggle(LED2);
		OSMboxPost(Mbox1, &MboxDataPost);
    }
}
/******************************************************************************************/
static  void  Task4 (void *p_arg)
{
    (void)p_arg;

    while (1) {
		OSSemPost(Sema1);
    	LED_Toggle(LED3);
        OSTimeDly(100);        // Delai en TICKS (1 TICKS=1milisec)
    }
}
/******************************************************************************************/

void Init_IO_Usager(void)
{
	   static const gpio_map_t USART_GPIO_MAP =
	     {
	       {AVR32_USART1_RXD_0_0_PIN, AVR32_USART1_RXD_0_0_FUNCTION},
	       {AVR32_USART1_TXD_0_0_PIN, AVR32_USART1_TXD_0_0_FUNCTION}
	     };
	    // Assigner les pins du GPIO a etre utiliser par le USART1.
	    gpio_enable_module(USART_GPIO_MAP,sizeof(USART_GPIO_MAP) / sizeof(USART_GPIO_MAP[0]));

	    // Initialise le USART1 en mode seriel RS232, a PBA=48/2MHz.
	    init_dbg_rs232(24000000);

	    print_dbg("UCOS-II Demo2 de LOG-550...");
}


